<?php


namespace Melon\Command;

use FastRoute\Dispatcher;
use Melon\Foundation\Request;
use Melon\Foundation\Response;
use Pimple\Container;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use const LOCK_EX;

class ServerStartCommand extends Command
{
    protected Container $container;

    protected static $defaultName = "serve:start";

    protected function configure()
    {
        $this->setDescription("server start command")
            ->setHelp("server start command");
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $this->container = $this->getApplication()->getContainer();

        // 检测是否在运行
        $pid_file_path = $this->container['base_path'] . "/storage/serve.pid";

        $file_resource = fopen($pid_file_path, 'w+');

        if (flock($file_resource, LOCK_EX)) {
            $output->writeln('<fg=green>fail</>');
        }

        fwrite($file_resource, posix_getpid());

        // 启动监听
        $stream = stream_socket_server("tcp://127.0.0.1:8000", $errno, $errstr);

        if (!$stream) {
            echo "$errstr ($errno)<br />\n";
        } else {
            while ($conn = stream_socket_accept($stream, -1, $remote_address)) {
                stream_set_read_buffer($conn, true);

                $request = new Request();
                $request->parse($conn, $remote_address);

                /** @var Dispatcher $route */
                $route = $this->container['route'];
                $route_info = $route->dispatch($request->method(), $request->uri());
                switch ($route_info[0]) {
                    case Dispatcher::NOT_FOUND:
                        $response = new Response('', 404);
                        break;
                    case Dispatcher::METHOD_NOT_ALLOWED:
                        $response = new Response('', 405);
                        break;
                    case Dispatcher::FOUND:
                        [$controller, $method] = explode("@", $route_info[1]['uses']);

                        $instance = new $controller;
                        $response = $instance->$method();

                        break;
                    default:
                        $response = new Response('', 500);
                        break;
                }

                $response->send($conn);

                unset($response);
            }
            fclose($stream);
        }

        return 0;
    }
}
